package com.mnemonic.game;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;

import javax.xml.bind.annotation.XmlRootElement;

import com.mnemonic.level.Level;
import com.mnemonic.player.Player;
import com.mnemonic.storage.StorageAble;
import com.mnemonic.utils.DateUtils;
import com.mnemonic.utils.Ints;

/**
 * 游戏数据
 * 
 * @author lifeng
 * @date 2021/05/13
 */
@XmlRootElement
public class Game implements StorageAble {

    private static final long serialVersionUID = 1L;

    /**
     * 一次服务运行开启计数
     */
    private static AtomicInteger count = new AtomicInteger(1);

    private String id;
    private String name;
    private Integer bout; // 回合应该从1 开，如果为 0 表示初始化。随机选择一个开始第一回合
    private Level level;
    private List<Player> players;
    private List<Bout> bouts = new ArrayList<>();
    private int[][] mineMap;
    private Boolean inited = false;

    public Boolean getInited() {
        return inited;
    }

    public void setInited(Boolean inited) {
        this.inited = inited;
    }

    public int[][] getMineMap() {
        return mineMap;
    }

    public void setMineMap(int[][] mineMap) {
        this.mineMap = mineMap;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Level getLevel() {
        return level;
    }

    public void setLevel(Level level) {
        this.level = level;
    }

    public List<Player> getPlayers() {
        return players;
    }

    public void setPlayers(List<Player> players) {
        this.players = players;
    }

    public List<Bout> getBouts() {
        return bouts;
    }

    public void setBouts(List<Bout> bouts) {
        this.bouts = bouts;
    }

    /**
     * 开启新一轮 ： 回合制
     * 
     * @return
     */
    public Bout newBout() {
        int index = 0;
        if (bout == null || bout < 0) {
            index = Ints.random(this.players.size());
            bout = index;
        } else {
            index = ++bout % this.players.size();
        }

        // 这一回合的玩家
        Player player = this.players.get(index);
        Bout bout = new Bout();
        bout.setPlayer(player);
        bout.setMaxops(this.level.getBoutOps());

        // 保存回合数据
        this.bouts.add(bout);
        return bout;
    }

    /**
     * 布雷的方法 <br>
     * 0b00000000 <br>
     * 0b00000001 用最后一位表示有雷或无雷 <br>
     * 0b00000110 用倒数第二和第三位表示格子的状态 00： 表示没有开 01： 开了 10： 插旗 <br>
     * 0b01111000第2、3、4、5位表示雷的数量 <br>
     */
    public void burnMine() {
        this.inited = true;

        Random rd = new Random();
        int mineCount = this.level.getMine();
        int rows = this.level.getRow();
        int cols = this.level.getCol();
        int x, y;
        for (int i = 0; i < mineCount;) {
            x = rd.nextInt(rows);
            y = rd.nextInt(cols);

            // 此区域已经点开了 -- 针对第一次点击后布雷
            if ((mineMap[x][y] & 0b00000100) == 0b00000100) {
                continue;
            }

            // 000
            // 001
            // 110
            // 101
            // 将这个位置周围的雷的数量加一
            // 说明没有雷
            if ((mineMap[x][y] & 0b00000001) == 0b00000000) {

                // 将雷放到这个位置
                mineMap[x][y] = 0b00000001;

                // 正上方
                if (x - 1 >= 0) {
                    mineMap[x - 1][y] += 0b000001000;
                }

                // // 上面的左边
                // if (x - 1 >= 0 && y - 1 >= 0) {
                // mineMap[x - 1][y - 1] += 0b000001000;
                // }
                //
                // // 上面的右边
                // if (x - 1 >= 0 && y + 1 < cols) {
                // mineMap[x - 1][y + 1] += 0b000001000;
                // }

                // 正下方
                if (x + 1 < rows) {
                    mineMap[x + 1][y] += 0b000001000;
                }

                // // 下面的左边
                // if (x + 1 < rows && y - 1 >= 0) {
                // mineMap[x + 1][y - 1] += 0b000001000;
                // }
                //
                // // 下面的右边
                // if (x + 1 < rows && y + 1 < cols) {
                // mineMap[x + 1][y + 1] += 0b000001000;
                // }

                // 左
                if (y - 1 >= 0) {
                    mineMap[x][y - 1] += 0b000001000;
                }

                // 右
                if (y + 1 < cols) {
                    mineMap[x][y + 1] += 0b000001000;
                }
                ++i;
            }
        }
    }

    /**
     * 重新开启一场游戏, 创建 level 和 player 的副本，保证在一场游戏中的数据不会覆盖全局数据
     * 
     * @param level
     * @param players
     * @return
     */
    public static Game newGame(Level level, List<Player> players) {
        Game game = new Game();
        game.setId(UUID.randomUUID().toString());
        game.setName(DateUtils.getTodayStr("yyyy年MM月dd日") + "第" + count.getAndIncrement() + "场");
        try {
            game.setLevel(level.clone());
            List<Player> copys = new ArrayList<>();
            for (Player player : players) {
                copys.add(player.clone());
            }
            game.setPlayers(copys);
        } catch (Exception e) {
        }

        // 创建雷区 -- 默认会初始化为0
        game.setMineMap(new int[level.getRow()][level.getCol()]);

        // 测试是否能需改原生的数据
        // game.getLevel().setBoutOps(100000);
        // System.out.println(level.getBoutOps());
        return game;
    }
}
